package com.miaoxun.controller;


import com.github.pagehelper.Page;

import com.miaoxun.common.encrypt.Encrypt;
import com.miaoxun.dao.util.ClassUtil;
import com.miaoxun.domain.enums.ErrEnum;
import com.miaoxun.domain.entity.Menu;
import com.miaoxun.domain.entity.Role;
import com.miaoxun.domain.entity.Task;
import com.miaoxun.domain.entity.User;
import com.miaoxun.domain.model.*;
import com.miaoxun.domain.param.BaseParam;
import com.miaoxun.domain.param.RoleParam;
import com.miaoxun.domain.param.UserParam;
import com.miaoxun.domain.util.PageUtil;
import com.miaoxun.service.MenuService;
import com.miaoxun.service.RoleService;
import com.miaoxun.service.SessionService;
import com.miaoxun.service.UserService;
import com.miaoxun.service.impl.SysService;
import com.miaoxun.service.timer.quartz.job.MeJob;
import com.miaoxun.service.util.TaskService;
import com.miaoxun.web.shiro.ShiroUtils;
import com.miaoxun.web.util.StreamUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping(value = "/sys/")
public class SystemController extends BaseController {
    /*******************************************************************/
    @Autowired
    SysService sysService;

    @Autowired
    TaskService taskService;

    @Autowired
    RoleService roleService;
/*******************************************************************/
    /*********************************用户相关**************************************************/

    @Autowired
    UserService userService;
    /**********************************************menu**************************************************/

    @Autowired
    MenuService menuService;
    /**********************************************在线用户*****************************************************/

    @Autowired
    SessionService sessionService;

    /**
     * @return
     */

    @ApiOperation(value = "代码生成list")
    @PostMapping(value = "/gen/lists")
    @ResponseBody
    public TableModel getTables(@ApiParam(value = "param") @RequestBody BaseParam param) {
        DataModel<List<SysModel>> dm = sysService.GetTables(param);
        return TableModel.TABLE(dm.getCount(), dm.getList());
    }

    @ApiOperation(value = "生成可用代码", notes = "生成可用代码")
    @GetMapping(value = "/gen/code")
    @ResponseBody
    public void genCode(HttpServletResponse response, @RequestParam(value = "tableName", required = false) String[] tableName) throws IOException {

        if (tableName == null || tableName.length < 1) {
            List<SysModel> l = sysService.list();
            tableName = new String[l.size()];
            int i = 0;
            for (SysModel m : l) {
                tableName[i] = m.getTableName();
                i++;
            }
        }
        byte[] data = sysService.generatorCode(tableName);
        StreamUtil.RESPONSE(response, data, "gen.zip");
    }

    /**************************************定时任务*********************/

    @RequiresPermissions("sys:job:job")
    @GetMapping("/job")
    public String job() {
        return "system/job/job";
    }

    @RequiresPermissions("sys:job:add")
    @GetMapping("/job/add")
    public String jobAdd() {
        return "system/job/add";
    }

    @RequiresPermissions("sys:job:edit")
    @GetMapping("/job/edit/{id}")
    public String jobEdit(@PathVariable("id") Long id, Model model) {
        Task job = taskService.getModelById(id);
        model.addAttribute("job", job);
        return "system/job/edit";
    }

    @ApiOperation(value = "定时任务列表", notes = "定时任务列表")
    @PostMapping(value = "/tasks/list")
    @ResponseBody
    public TableModel taskList(@RequestBody BaseParam param) {
        DataModel<List<Task>> dm = taskService.GetTables(param);
        return TableModel.TABLE(dm.getCount(), dm.getList());
    }

    /**
     * 保存
     */
    @RequiresPermissions("sys:job:add")
    @ResponseBody
    @PostMapping("/job/save")
    public ResultModel jobSave(Task taskScheduleJob) {

        if (taskService.save(taskScheduleJob)!=null) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.INSERT.getCode(), ErrEnum.INSERT.getMsg());
    }

    /**
     * 修改
     */
    @RequiresPermissions("sys:job:edit")
    @ResponseBody
    @PostMapping("/job/update")
    public ResultModel jobUpdate(Task taskScheduleJob) {
        if (taskService.update(taskScheduleJob))
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), ErrEnum.UPDATE.getMsg());
    }

    /**
     * 删除
     */
    @PostMapping("/job/remove")
    @ResponseBody
    public ResultModel jobRemove(Long id) {

        if (taskService.deleteById(id)) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.DELETE.getCode(), ErrEnum.DELETE.getMsg());
    }

    /**
     * 删除
     */
    @PostMapping("/job/batchRemove")
    @ResponseBody
    public ResultModel remove(@RequestParam("ids[]") Long[] ids) {

        if (taskService.batchRemove(ids)>0) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.DELETE.getCode(), ErrEnum.DELETE.getMsg());
    }

    /**************************************定时任务*********************/

    @PostMapping(value = "/job/changeJobStatus")
    @ResponseBody
    public ResultModel changeJobStatus(Long id, String cmd) {

        String label;
        if ("start".equals(cmd)) {
            label = "启动";
        } else {
            label = "停止";
        }
        try {
            taskService.changeStatus(id, cmd);
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), "任务" + label + "成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), "任务" + label + "失败");
    }

    @ApiOperation(value = "添加定时任务", notes = "添加定时任务")
    @PostMapping(value = "/task/add")
    @ResponseBody
    public ResultModel insertTask(@RequestBody Task param) {
        if (taskService.save(param)!=null) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.INSERT.getCode(), ErrEnum.INSERT.getMsg());
    }

    @ApiOperation(value = "获取job子类", notes = "获取job子类,添加在定时中选择")
    @PostMapping(value = "/task/jobs")
    @ResponseBody
    public ResultModel taskJobs() throws IOException, ClassNotFoundException {
   List<Class<?>> clazzes = ClassUtil.getAllAssignedClass(MeJob.class);
        return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), "", clazzes);
    }

    @PostMapping("/user/exit")
    @ResponseBody
    public boolean userExit(String username) {
        // 存在，不通过，false
        return !userService.exit(username);
    }

    @RequiresPermissions("sys:user:resetPwd")
    @GetMapping("/user/resetPwd/{id}")
    public String useresetPwd(@PathVariable("id") Long userId, Model model) {
        User userDO = new User();
        userDO.setUserId(userId);
        model.addAttribute("user", userDO);
        return "system/user/reset_pwd";
    }

    @RequiresPermissions("sys:user:resetPwd")
    @PostMapping("/user/resetPwd")
    @ResponseBody
    public ResultModel userResetPwd(User user) {

        user.setPassword(Encrypt.LoginPwd.Encode(user.getPassword()));
        if (userService.resetPwd(user)  ) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), ErrEnum.UPDATE.getMsg());
    }

    @RequiresPermissions("sys:user:user")
    @GetMapping("/user")
    public String user() {
        return "system/user/user";
    }

    @PostMapping("/user/dept/list")
    @ResponseBody
    public TableModel userDeptList(@ApiParam(value = "param") @RequestBody UserParam param) {
        Page page = PageUtil.startPage(param.getOffset(), param.getLimit(), param.getOrder(), param.getSort());
        List<User> l = userService.listByDept(param);
        return TableModel.TABLE(page.getTotal(), l);
    }

    @PostMapping("/user/list")
    @ResponseBody
    public TableModel userList(@ApiParam(value = "param") @RequestBody BaseParam param) {
        Page page = PageUtil.startPage(param.getOffset(), param.getLimit(), param.getOrder(), param.getSort());
        List<User> l = userService.getAll();
        return TableModel.TABLE(page.getTotal(), l);
    }

    @RequiresPermissions("sys:user:add")
    @GetMapping("/user/add")
    public String userAdd(Model model) {
        List<Role> roles = roleService.getAll();
        model.addAttribute("roles", roles);
        return "system/user/add";
    }

    @RequiresPermissions("sys:user:edit")
    @GetMapping("/user/edit/{id}")
    public String userEdit(Model model, @PathVariable("id") Long id) {
        UserModel userDO = userService.findUserDeptById(id);
        model.addAttribute("user", userDO);
        List<Role> roles = roleService.listByUserId(id);
        model.addAttribute("roles", roles);
        return "system/user/edit";
    }

    @RequiresPermissions("sys:user:add")
    @PostMapping("/user/save")
    @ResponseBody
    ResultModel userSave(UserParam user) {
        user.setUserIdCreate(ShiroUtils.getUserId());
        user.setPassword(Encrypt.LoginPwd.Encode(user.getPassword()));
        if (userService.addUserAndRole(user)) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.INSERT.getCode(), ErrEnum.INSERT.getMsg());
    }

    /*********************************用户相关**************************************************/

    @RequiresPermissions("sys:user:edit")
    @PostMapping("/user/update")
    @ResponseBody
    ResultModel userUpdate(UserParam user) {
        if (user.getUserId() == ShiroUtils.getUserId()) {
            return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), "不能修改本身权限");
        }
        if (userService.updateUserAndRole(user) ) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), ErrEnum.UPDATE.getMsg());
    }

    @RequiresPermissions("sys:user:remove")
    @PostMapping("/user/remove")
    @ResponseBody
    ResultModel useRemove(Long id) {
        if (userService.deleteUserAndRoleById(id) ) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        }
        return ResultModel.SUCCESS(ErrEnum.DELETE.getCode(), ErrEnum.DELETE.getMsg());
    }

    /****************************************************角色******************************/


    @RequiresPermissions("sys:role:role")
    @PostMapping("/role/list")
    @ResponseBody
    public List<Role> roleList() {
        List<Role> roles = roleService.getAll();
        return roles;
    }

    @RequiresPermissions("sys:role:edit")
    @PostMapping("/role/update")
    @ResponseBody
    public ResultModel update(RoleParam role) {
        if (roleService.updateRole(role)) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        } else {
            return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), ErrEnum.UPDATE.getMsg());
        }
    }

    @RequiresPermissions("sys:role:remove")
    @PostMapping("/role/remove")
    @ResponseBody
    public ResultModel remove(Long id) {
        if (roleService.deleteById(id)) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        } else {
            return ResultModel.SUCCESS(ErrEnum.DELETE.getCode(), ErrEnum.DELETE.getMsg());
        }
    }

    /***********************************endrole***************************/

    @RequiresPermissions("sys:role:batchRemove")
    @PostMapping("/role/batchRemove")
    @ResponseBody
    public ResultModel roleBatchRemove(@RequestParam("ids[]") Long[] ids) {
        int r = roleService.batchRemove(ids);
        return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
    }

    @RequiresPermissions("sys:role:add")
    @PostMapping("/role/save")
    @ResponseBody
    public ResultModel roleSave(Role role) {
        role.setGmtCreate(new Date());
        role.setGmtModified(new Date());
        role.setUserIdCreate(ShiroUtils.getUserId());
        if (roleService.save(role)!=null) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        } else {
            return ResultModel.SUCCESS(ErrEnum.INSERT.getCode(), ErrEnum.INSERT.getMsg());
        }
    }

    /*******************************************html**************************************/


    @ApiIgnore
    @GetMapping(value = "/tasks")
    public String tasks() {
        return "/sys/tasks";
    }

    @RequiresPermissions("sys:role:role")
    @GetMapping(value = "/role")
    public String role() {
        return "system/role" + "/role";
    }

    @RequiresPermissions("sys:role:add")
    @GetMapping("/role/add")
    public String roleAdd() {
        return "system/role" + "/add";
    }


    /***********************************************/

    @RequiresPermissions("sys:role:edit")
    @GetMapping("/role/edit/{id}")
    public String roleEdit(@PathVariable("id") Long id, Model model) {
        Role roleDO = roleService.getModelById(id);
        model.addAttribute("role", roleDO);
        return "system/role" + "/edit";
    }

    @RequiresPermissions("sys:gen:list")
    @GetMapping("/gen/list")
    public String genList() {
        return "system/gen/list";
    }


    @RequiresPermissions("sys:menu:menu")
    @GetMapping(value = "/menu")
    String menu() {
        return "system/menu/menu";
    }

    @RequiresPermissions("sys:menu:menu")
    @PostMapping("/menu/list")
    @ResponseBody
    public List<Menu> menuList() {
        List<Menu> menus = menuService.getAll();
        return menus;
    }

    @RequiresPermissions("sys:menu:add")
    @GetMapping("/menu/add/{pId}")
    public String menuAdd(Model model, @PathVariable("pId") Long pId) {
        model.addAttribute("pId", pId);
        if (pId == 0) {
            model.addAttribute("pName", "根目录");
        } else {

        }
        return "system/menu/add";
    }

    @RequiresPermissions("sys:menu:edit")
    @GetMapping("/menu/edit/{id}")
    public String menuEdit(Model model, @PathVariable("id") Long id) {
        model.addAttribute("menu", menuService.getModelById(id));
        return "system/menu/edit";
    }

    @RequiresPermissions("sys:menu:add")
    @PostMapping("/menu/save")
    @ResponseBody
    public ResultModel menuSave(Menu menu) {
        if (menuService.save(menu)!=null) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg(), "");
        } else {
            return ResultModel.SUCCESS(0, "", "");
        }
    }

    @RequiresPermissions("sys:menu:edit")
    @PostMapping("/menu/update")
    @ResponseBody
    ResultModel menuUpdate(Menu menu) {

        if (menuService.update(menu)) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        } else {
            return ResultModel.SUCCESS(ErrEnum.UPDATE.getCode(), ErrEnum.UPDATE.getMsg());
        }
    }

    @ApiOperation(value = "菜单删除", notes = "菜单删除")
    @RequiresPermissions("sys:menu:remove")
    @PostMapping("/menu/remove")
    @ResponseBody
    ResultModel menuRemove(@ApiParam(value = "id", name = "id", required = true) Long id) {
        if (menuService.deleteById(id)) {
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        } else {
            return ResultModel.SUCCESS(ErrEnum.DELETE.getCode(), ErrEnum.DELETE.getMsg());
        }

    }

    @GetMapping("/menu/tree")
    @ResponseBody
    Tree<Menu> tree() {
        Tree<Menu> tree = menuService.getTree();
        return tree;
    }

    /**********************************************menu**************************************************/

    @GetMapping("/menu/tree/{roleId}")
    @ResponseBody
    Tree<Menu> menuTree(@PathVariable("roleId") Long roleId) {
        Tree<Menu> tree = menuService.getTree(roleId);
        return tree;
    }

    @GetMapping(value = "/online")
    public String online() {
        return "system/online/online";
    }

    @ResponseBody
    @PostMapping("/online/list")
    public List<UserOnline> onlineList() {
        return sessionService.list();
    }

    @ResponseBody
    @PostMapping("/online/forceLogout/{sessionId}")
    public ResultModel forceLogout(@PathVariable("sessionId") String sessionId, RedirectAttributes redirectAttributes) {
        try {
            sessionService.forceLogout(sessionId);
            return ResultModel.SUCCESS(ErrEnum.SUCCESS.getCode(), ErrEnum.SUCCESS.getMsg());
        } catch (Exception e) {
            return ResultModel.SUCCESS(ErrEnum.DELETE.getCode(), ErrEnum.DELETE.getMsg());
        }


    }

    @ResponseBody
    @PostMapping("/online/sessionList")
    public Collection<Session> sessionList() {
        return sessionService.sessionList();
    }
/**********************************************在线用户*****************************************************/
}
